﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace L4View.BusinessModel
{
    using Infrastructure;

    public class LogMonitorGroup<TMonitor> where TMonitor : class, ILoggingMonitor
    {
        private readonly string _name;

        private readonly string _fileName;

        private readonly HashSet<TMonitor> _monitors;

        private readonly IMonitorFactory _monitorFactory;

        private readonly ISourcePath _sourcePath;

        public LogMonitorGroup(string name, string fileName, IMonitorFactory monitorFactory)
        {
            _name = name;
            _fileName = fileName;
            _monitorFactory = monitorFactory;
            _monitors = new HashSet<TMonitor>();
            _sourcePath = new FileSourcePath(fileName);
        }

        public string Name
        {
            get { return _name; }
        }

        public string FileName
        {
            get { return _fileName; }
        }

        public TMonitor AddMonitorBy(Guid uniqueId)
        {
            var monitor = GetMonitorBy(uniqueId) as TMonitor;

            if (monitor == null)
            {
                try
                {
                    monitor = _monitorFactory.CreateMonitorById(uniqueId) as TMonitor;

                    if (monitor == null)
                        throw new InvalidCastException("Monitor is derived from a wrong base type.");

                    InitializeMonitor(monitor);

                    _monitors.Add(monitor);
                }
                catch (NotSupportedException)
                {
                    monitor = null;
                }
            }

            return monitor;            
        }

        public TMonitor GetMonitorBy(Guid uniqueId)
        {
            return _monitors
                .FirstOrDefault( monitor => monitor.UniqueId == uniqueId );
        }

        public bool RemoveMonitor(TMonitor logMonitor)
        {
            return _monitors.Remove(logMonitor);
        }

        public bool RemoveMonitorBy(Guid uniqueId)
        {
            return _monitors.RemoveWhere((logMonitor) => logMonitor.UniqueId == uniqueId) > 0;
        }

        private void InitializeMonitor(TMonitor monitor)
        {
            monitor.AssignSourcePath(_sourcePath);        
        }

        class FileSourcePath : ISourcePath
        {
            private readonly string _filePath;

            public FileSourcePath(string filePath)
            {
                _filePath = filePath;
            }

            public string Path
            {
                get { return _filePath; }
            }
        }

    }
}
